/**
  ******************************************************************************
  * @file    stm32l475e_iot01_bus.c
  * @author  MCD Application Team
  * @brief   This file provides a set of firmware functions to manage bus
  *          available on B-L475E-IOT01 board (MB1297) from
  *          STMicroelectronics.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4_bus.h"

/** @addtogroup BSP
  * @{
  */

/** @addtogroup STM32L475E_IOT01
  * @{
  */

/** @defgroup STM32L475E_IOT01_BUS STM32L475E_IOT01 BUS
  * @{
  */







/** @defgroup STM32L475E_IOT01_BUS_Exported_Variables STM32L475E_IOT01 BUS Exported Variables
  * @{
  */
extern I2C_HandleTypeDef hi2c1;
/**
  * @}
  */

/** @defgroup STM32L475E_IOT01_BUS_Private_Function_Prototypes STM32L475E_IOT01 BUS Private Function Prototypes
  * @{
  */
static int32_t  I2C1_WriteReg(uint16_t DevAddr, uint16_t MemAddSize, uint16_t Reg, uint8_t *pData, uint16_t Length);
static int32_t  I2C1_ReadReg(uint16_t DevAddr, uint16_t MemAddSize, uint16_t Reg, uint8_t *pData, uint16_t Length);
static int32_t  I2C1_WriteData(uint16_t DevAddr, uint8_t *pData, uint16_t Length);
static int32_t  I2C1_ReadData(uint16_t DevAddr, uint8_t *pData, uint16_t Length);
/**
  * @}
  */


/** @defgroup STM32L475E_IOT01_BUS_Exported_Functions STM32L475E_IOT01 BUS Exported Functions
  * @{
  */

/**
  * @brief  Write 8bit values in registers of the device through BUS.
  * @param  DevAddr Device address on Bus.
  * @param  Reg     The target register start address to write.
  * @param  pData   Pointer to data buffer.
  * @param  Length  Number of data.
  * @retval BSP status.
  */
int32_t BSP_I2C1_WriteReg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length)
{
  return I2C1_WriteReg(DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length);
}

/**
  * @brief  Read a 8bit values in registers of the device through BUS.
  * @param  DevAddr Device address on Bus.
  * @param  Reg     The target register start address to read.
  * @param  pData   Pointer to data buffer.
  * @param  Length  Number of data.
  * @retval BSP status
  */
int32_t BSP_I2C1_ReadReg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length)
{
  return I2C1_ReadReg(DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length);
}

/**
  * @brief  Write 16bit values in registers of the device through BUS.
  * @param  DevAddr Device address on Bus.
  * @param  Reg     The target register start address to write.
  * @param  pData   Pointer to data buffer.
  * @param  Length  Number of data.
  * @retval BSP status.
  */
int32_t BSP_I2C1_WriteReg16(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length)
{
  return I2C1_WriteReg(DevAddr, Reg, I2C_MEMADD_SIZE_16BIT, pData, Length);
}

/**
  * @brief  Read a 16bit values in registers of the device through BUS.
  * @param  DevAddr Device address on Bus.
  * @param  Reg     The target register start address to read.
  * @param  pData   Pointer to data buffer.
  * @param  Length  Number of data.
  * @retval BSP status
  */
int32_t BSP_I2C1_ReadReg16(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length)
{
  return I2C1_ReadReg(DevAddr, Reg, I2C_MEMADD_SIZE_16BIT, pData, Length);
}

/**
  * @brief  Write 8bit data through BUS.
  * @param  DevAddr Device address on Bus.
  * @param  pData   Pointer to data buffer.
  * @param  Length  Number of data.
  * @retval BSP status.
  */
int32_t BSP_I2C1_WriteData(uint16_t DevAddr, uint8_t *pData, uint16_t Length)
{
  return I2C1_WriteData(DevAddr, pData, Length);
}

/**
  * @brief  Read 8bit data through BUS.
  * @param  DevAddr Device address on Bus.
  * @param  pData   Pointer to data buffer.
  * @param  Length  Number of data.
  * @retval BSP status
  */
int32_t BSP_I2C1_ReadData(uint16_t DevAddr, uint8_t *pData, uint16_t Length)
{
  return I2C1_ReadData(DevAddr, pData, Length);
}

/**
  * @brief  Checks if target device is ready for communication.
  * @param  DevAddr  Target device address.
  * @param  Trials   Number of trials.
  * @retval BSP status
  */
int32_t BSP_I2C1_IsReady(uint16_t DevAddr, uint32_t Trials)
{
  int32_t status = BSP_ERROR_NONE;

  if (HAL_I2C_IsDeviceReady(&hi2c1, DevAddr, Trials, BUS_I2C1_TIMEOUT) != HAL_OK)
  {
    status = BSP_ERROR_BUSY;
  }

  return status;
}



/**
  * @brief  Provide a tick value in millisecond.
  * @retval Tick value.
  */
int32_t BSP_GetTick(void)
{
  uint32_t ret;
  ret = HAL_GetTick();
  return (int32_t)ret;
}


/**
  * @brief  Write values in registers of the device through BUS.
  * @param  DevAddr    Device address on Bus.
  * @param  Reg        The target register start address to write.
  * @param  MemAddSize Size of internal memory address.
  * @param  pData      The target register values to be written.
  * @param  Length     Number of data.
  * @retval BSP status.
  */
static int32_t I2C1_WriteReg(uint16_t DevAddr, uint16_t Reg, uint16_t MemAddSize, uint8_t *pData, uint16_t Length)
{
  int32_t  status = BSP_ERROR_NONE;
  uint32_t hal_error;

  if (HAL_I2C_Mem_Write(&hi2c1, DevAddr, Reg, MemAddSize, pData, Length, BUS_I2C1_TIMEOUT) != HAL_OK)
  {
    hal_error = HAL_I2C_GetError(&hi2c1);
    if ((hal_error & HAL_I2C_ERROR_BERR) != 0U)
    {
      status = BSP_ERROR_BUS_PROTOCOL_FAILURE;
    }
    else if ((hal_error & HAL_I2C_ERROR_ARLO) != 0U)
    {
      status = BSP_ERROR_BUS_ARBITRATION_LOSS;
    }
    else if ((hal_error & HAL_I2C_ERROR_AF) != 0U)
    {
      status = BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE;
    }
    else if (((hal_error & HAL_I2C_ERROR_TIMEOUT) != 0U) || ((hal_error & HAL_I2C_ERROR_SIZE) != 0U))
    {
      status = BSP_ERROR_BUS_TRANSACTION_FAILURE;
    }
    else
    {
      status = BSP_ERROR_PERIPH_FAILURE;
    }    
  }

  return status;
}

/**
  * @brief  Read values in registers of the device through BUS.
  * @param  DevAddr    Device address on Bus.
  * @param  Reg        The target register start address to read.
  * @param  MemAddSize Size of internal memory address.
  * @param  pData      The target register values to be read.
  * @param  Length     Number of data.
  * @retval BSP status.
  */
static int32_t I2C1_ReadReg(uint16_t DevAddr, uint16_t Reg, uint16_t MemAddSize, uint8_t *pData, uint16_t Length)
{
  int32_t  status = BSP_ERROR_NONE;
  uint32_t hal_error;

  if (HAL_I2C_Mem_Read(&hi2c1, DevAddr, Reg, MemAddSize, pData, Length, BUS_I2C1_TIMEOUT) != HAL_OK)
  {
    hal_error = HAL_I2C_GetError(&hi2c1);
    if ((hal_error & HAL_I2C_ERROR_BERR) != 0U)
    {
      status = BSP_ERROR_BUS_PROTOCOL_FAILURE;
    }
    else if ((hal_error & HAL_I2C_ERROR_ARLO) != 0U)
    {
      status = BSP_ERROR_BUS_ARBITRATION_LOSS;
    }
    else if ((hal_error & HAL_I2C_ERROR_AF) != 0U)
    {
      status = BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE;
    }
    else if (((hal_error & HAL_I2C_ERROR_TIMEOUT) != 0U) || ((hal_error & HAL_I2C_ERROR_SIZE) != 0U))
    {
      status = BSP_ERROR_BUS_TRANSACTION_FAILURE;
    }
    else
    {
      status = BSP_ERROR_PERIPH_FAILURE;
    }    
  }
  return status;
}

/**
  * @brief  Write data through BUS.
  * @param  DevAddr    Device address on Bus.
  * @param  pData      The target register values to be written.
  * @param  Length     Number of data.
  * @retval BSP status.
  */
static int32_t I2C1_WriteData(uint16_t DevAddr, uint8_t *pData, uint16_t Length)
{
  int32_t  status = BSP_ERROR_NONE;
  uint32_t hal_error;

  if (HAL_I2C_Master_Transmit(&hi2c1, DevAddr, pData, Length, BUS_I2C1_TIMEOUT) != HAL_OK)
  {
    hal_error = HAL_I2C_GetError(&hi2c1);
    if ((hal_error & HAL_I2C_ERROR_BERR) != 0U)
    {
      status = BSP_ERROR_BUS_PROTOCOL_FAILURE;
    }
    else if ((hal_error & HAL_I2C_ERROR_ARLO) != 0U)
    {
      status = BSP_ERROR_BUS_ARBITRATION_LOSS;
    }
    else if ((hal_error & HAL_I2C_ERROR_AF) != 0U)
    {
      status = BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE;
    }
    else if (((hal_error & HAL_I2C_ERROR_TIMEOUT) != 0U) || ((hal_error & HAL_I2C_ERROR_SIZE) != 0U))
    {
      status = BSP_ERROR_BUS_TRANSACTION_FAILURE;
    }
    else
    {
      status = BSP_ERROR_PERIPH_FAILURE;
    }    
  }

  return status;
}

/**
  * @brief  Read data through BUS.
  * @param  DevAddr    Device address on Bus.
  * @param  pData      The target register values to be read.
  * @param  Length     Number of data.
  * @retval BSP status.
  */
static int32_t I2C1_ReadData(uint16_t DevAddr, uint8_t *pData, uint16_t Length)
{
  int32_t  status = BSP_ERROR_NONE;
  uint32_t hal_error;

  if (HAL_I2C_Master_Receive(&hi2c1, DevAddr, pData, Length, BUS_I2C1_TIMEOUT) != HAL_OK)
  {
    hal_error = HAL_I2C_GetError(&hi2c1);
    if ((hal_error & HAL_I2C_ERROR_BERR) != 0U)
    {
      status = BSP_ERROR_BUS_PROTOCOL_FAILURE;
    }
    else if ((hal_error & HAL_I2C_ERROR_ARLO) != 0U)
    {
      status = BSP_ERROR_BUS_ARBITRATION_LOSS;
    }
    else if ((hal_error & HAL_I2C_ERROR_AF) != 0U)
    {
      status = BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE;
    }
    else if (((hal_error & HAL_I2C_ERROR_TIMEOUT) != 0U) || ((hal_error & HAL_I2C_ERROR_SIZE) != 0U))
    {
      status = BSP_ERROR_BUS_TRANSACTION_FAILURE;
    }
    else
    {
      status = BSP_ERROR_PERIPH_FAILURE;
    }    
  }
  return status;
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
